package pers.qianyu.module.comment.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import pers.qianyu.module.comment.dao.CommentDao;
import pers.qianyu.module.comment.exception.CommentErrorCodeEnum;
import pers.qianyu.module.comment.exception.CommentException;
import pers.qianyu.module.comment.service.CommentService;
import pers.qianyu.module.core.comm.Pagination;
import pers.qianyu.module.core.domain.comment.converter.CommentConverter;
import pers.qianyu.module.core.domain.comment.dto.CommentDTO;
import pers.qianyu.module.core.domain.comment.entity.CommentPO;
import pers.qianyu.module.core.domain.comment.query.CommentQuery;
import pers.qianyu.module.core.domain.comment.vo.CommentVO;
import pers.qianyu.module.core.domain.system.vo.SimpleUserVO;
import pers.qianyu.module.core.util.DateTimeUtil;
import pers.qianyu.module.image.listener.events.InsertCommentEvent;
import pers.qianyu.module.image.service.ImageService;
import pers.qianyu.module.system.service.SysUserService;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author mizzle rain
 * @date 2021-04-07 19:43
 */
@Service("commentService")
public class CommentServiceImpl implements CommentService {
    @Autowired
    private CommentDao commentDao;
    @Autowired
    private CommentConverter commentConverter;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private ImageService imageService;
    @Autowired
    private ApplicationContext applicationContext;

    /**
     * 根据评论对象 id 获取下面所有评论
     *
     * @param topicId 表示评论对象id
     * @return 评论对象列表
     */
    public List<CommentVO> findCommentsByTopicId(Long topicId) {
        QueryWrapper<CommentPO> wrapper = new QueryWrapper<>();
        wrapper.eq("topic_id", topicId);
        List<CommentPO> commentPOList = commentDao.selectList(wrapper);
        List<CommentVO> commentVOList = commentPOList.stream()
                .map(commentConverter::convertToVO)
                .collect(Collectors.toList());
        List<CommentVO> result = new ArrayList<>();
        HashMap<Long, CommentVO> map = new HashMap<>();
        for (CommentVO commentVO : commentVOList) {
            if (Objects.isNull(commentVO.getParentId())) {
                result.add(commentVO);
            }
            map.put(commentVO.getId(), commentVO);
        }
        for (CommentVO commentVO : commentVOList) {
            if (Objects.nonNull(commentVO.getParentId())) {
                CommentVO parent = map.get(commentVO.getParentId());
                if (Objects.nonNull(parent)) {
                    List<CommentVO> children = parent.getChildren();
                    children.add(commentVO);
                }
            }
        }
        return result;
    }

    /**
     * 插入一条评论
     *
     * @param commentDTO 评论传输对象
     */
    @Transactional(rollbackFor = Throwable.class)
    public void insert(CommentDTO commentDTO) {
        CommentPO commentPO = commentConverter.convertToPO(commentDTO);
        commentDao.insert(commentPO);
        imageService.addComments(commentDTO.getTopicId(), 1);
        // 插入一条通知
        applicationContext.publishEvent(new InsertCommentEvent(this, commentPO));
    }

    /**
     * 根据评论 id 查找评论
     *
     * @param id 评论 id
     * @return 查找结果
     */
    public CommentVO findById(Long id) {
        CommentPO commentPO = commentDao.selectById(id);
        if (Objects.isNull(commentPO)) {
            throw new CommentException(CommentErrorCodeEnum.INVALID_ID);
        }
        return commentConverter.convertToVO(commentPO);
    }

    /**
     * 条件查询
     *
     * @param commentQuery 查询条件
     * @return 分页信息
     */
    public Pagination<CommentVO> query(CommentQuery commentQuery) {
        QueryWrapper<CommentPO> wrapper = getQueryWrapper(commentQuery);
        Page<CommentPO> page = new Page<>(commentQuery.getPage(), commentQuery.getLimit());
        // 执行查询
        Page<CommentPO> commentPOPage = commentDao.selectPage(page, wrapper);
        // 转换
        Pagination<CommentVO> pagination = commentConverter.convertToPagination(commentPOPage);
        for (CommentVO commentVO : pagination.getRecords()) {
            SimpleUserVO simpleUserVO = sysUserService.querySimpleUserInfoById(commentVO.getCreatedBy());
            commentVO.setCreator(simpleUserVO);
        }
        if (StrUtil.isNotBlank(commentQuery.getKeywords())) {
            for (CommentVO record : pagination.getRecords()) {
                String content = record.getContent();
                String regex = String.format("(%s)", commentQuery.getKeywords());
                content = content.replaceAll(regex, "<font style='color:red;'>$1</font>");
                record.setContent(content);
            }
        }
        return pagination;
    }

    /**
     * 根据query对象构造QueryWrapper对象
     *
     * @param commentQuery 查询条件
     * @return QueryWrapper对象
     */
    private QueryWrapper<CommentPO> getQueryWrapper(CommentQuery commentQuery) {
        String createTimeStart = commentQuery.getCreateTimeStart();
        String createTimeEnd = commentQuery.getCreateTimeEnd();
        String updateTimeStart = commentQuery.getUpdateTimeStart();
        String updateTimeEnd = commentQuery.getUpdateTimeEnd();
        // 构造查询条件
        CommentPO commentPOForQuery = new CommentPO();
        commentPOForQuery.setTopicId(commentQuery.getTopicId());
        commentPOForQuery.setParentId(commentQuery.getParentId());
        commentPOForQuery.setCreatedBy(commentQuery.getCreatedBy());
        commentPOForQuery.setUpdatedBy(commentQuery.getUpdatedBy());
        QueryWrapper<CommentPO> wrapper = new QueryWrapper<>(commentPOForQuery);
        if (Objects.nonNull(createTimeStart)) {
            if (Objects.nonNull(createTimeEnd)) {
                wrapper.between("create_time", DateTimeUtil.parseDatetime(createTimeStart),
                        DateTimeUtil.parseDatetime(createTimeEnd));
            } else {
                wrapper.ge("create_time", DateTimeUtil.parseDatetime(createTimeStart));
            }
        }
        if (Objects.nonNull(updateTimeStart)) {
            if (Objects.nonNull(createTimeEnd)) {
                wrapper.between("update_time", DateTimeUtil.parseDatetime(updateTimeStart),
                        DateTimeUtil.parseDatetime(updateTimeEnd));
            } else {
                wrapper.ge("update_time", DateTimeUtil.parseDatetime(updateTimeStart));
            }
        }
        if (StrUtil.isNotBlank(commentQuery.getKeywords())) {
            wrapper.like("content", commentQuery.getKeywords());
        }
        return wrapper;
    }

    /**
     * 根据评论 ID 查询评论具体信息
     *
     * @param id 评论 ID
     */
    public void deleteById(Long id) {
        commentDao.deleteById(id);
    }

    @Override
    public void deleteByTopicId(Long topicId) {
        CommentPO commentPO = new CommentPO();
        commentPO.setTopicId(topicId);
        QueryWrapper<CommentPO> wrapper = new QueryWrapper<>(commentPO);
        commentDao.delete(wrapper);
    }
}
